package com.demo.java.OD151_200.OD195;

import java.util.*;

/**
 * @author bug菌
 * @Source 公众号：猿圈奇妙屋
 * @des： 【145889124】问题
 * @url： https://blog.csdn.net/weixin_43970743/article/details/删除重复数字后的最大数字
 */
public class OdMain {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long n = sc.nextLong();  // 读取输入的数字
        long tmp = n;
        int[] cnt = new int[10];  // 用来存储每个数字出现的次数
        List<Integer> s = new ArrayList<>();  // 存储数字的每一位
        int[] vis = new int[10];  // 标记每个数字是否已经在栈中
        // 拆分数字并存储
        while (tmp > 0) {
            cnt[(int) (tmp % 10)]++;  // 统计数字的每一位
            s.add((int) (tmp % 10));  // 将数字的每一位存入列表
            tmp /= 10;  // 移动到下一个数字
        }
        Collections.reverse(s);  // 逆序，方便栈操作

        Stack<Integer> st = new Stack<>();  // 栈，用于存储最终结果
        for (int i = 0; i < s.size(); ++i) {
            cnt[s.get(i)]--;  // 当前数字出现次数减一
            if (st.empty()) {
                st.push(s.get(i));  // 栈为空时直接压入当前数字
                vis[s.get(i)] = 1;  // 标记数字已入栈
            } else {
                // 如果栈不为空且栈顶小于当前数字，且栈顶数字还有出现的机会
                while (!st.empty() && st.peek() < s.get(i) && cnt[st.peek()] > 0 && vis[s.get(i)] == 0) {
                    vis[st.peek()] = 0;  // 标记栈顶数字出栈
                    st.pop();  // 出栈
                }
                if (vis[s.get(i)] == 0) {
                    st.push(s.get(i));  // 压入当前数字
                    vis[s.get(i)] = 1;  // 标记数字已入栈
                }
            }
        }

        // 从栈中生成最终结果
        long ans = 0, T = 1;  // T 是乘数，用来计算数字的位置
        while (!st.empty()) {
            int x = st.peek();
            st.pop();
            ans += x * T;  // 将数字和权重相乘
            T *= 10;  // 权重逐位增加
        }
        System.out.println(ans);  // 输出最终结果
    }
}